package 原子类;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.LongAccumulator;
import java.util.concurrent.atomic.LongAdder;

/**
 * @program: algorithm
 * @description:
 * @author: 陈恩涛
 * @create: 2022-08-29 19:36
 **/
public class AccumulatorCompareDemo {

    private static final int EXEC_TIMES = 1000000;
    private static final int THREAD_NUM = 50;

    public static void main(String[] args) {
        final ClickNumber clickNumber = new ClickNumber();

        long startTime;
        long endTime;

        final CyclicBarrier cyclicBarrier = new CyclicBarrier(THREAD_NUM + 1);

        startTime = System.currentTimeMillis();
        for (int i = 0; i < THREAD_NUM; i++) {
            new Thread(() -> {
                for (int j = 0; j < EXEC_TIMES; j++) {
                    clickNumber.clickBySynchronized();
                }
                try {
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }).start();
        }
        try {
            cyclicBarrier.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
        endTime = System.currentTimeMillis();
        System.out.println("synchronized------costTime: " + (endTime - startTime) + "毫秒, 结果为" + clickNumber.getNumber());

        startTime = System.currentTimeMillis();
        for (int i = 0; i < THREAD_NUM; i++) {
            new Thread(() -> {
                for (int j = 0; j < EXEC_TIMES; j++) {
                    clickNumber.clickByAtomicInteger();
                }
                try {
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }).start();
        }
        try {
            cyclicBarrier.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
        endTime = System.currentTimeMillis();
        System.out.println("atomicInteger------costTime: " + (endTime - startTime) + "毫秒, 结果为" + clickNumber.getAtomicInteger());

        startTime = System.currentTimeMillis();
        for (int i = 0; i < THREAD_NUM; i++) {
            new Thread(() -> {
                for (int j = 0; j < EXEC_TIMES; j++) {
                    clickNumber.clickByLongAdder();
                }
                try {
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }).start();
        }
        try {
            cyclicBarrier.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
        endTime = System.currentTimeMillis();
        System.out.println("LongAdder------costTime: " + (endTime - startTime) + "毫秒, 结果为" + clickNumber.getLongAdder());

        startTime = System.currentTimeMillis();
        for (int i = 0; i < THREAD_NUM; i++) {
            new Thread(() -> {
                for (int j = 0; j < EXEC_TIMES; j++) {
                    clickNumber.clickByLongAccumulator();
                }
                try {
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }).start();
        }
        try {
            cyclicBarrier.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
        endTime = System.currentTimeMillis();
        System.out.println("LongAccumulator------costTime: " + (endTime - startTime) + "毫秒, 结果为" + clickNumber.getLongAccumulator());

    }
}

class ClickNumber{

    private volatile int number = 0;

    public synchronized void clickBySynchronized() {
        number++;
    }

    private AtomicInteger atomicInteger = new AtomicInteger();

    public void clickByAtomicInteger() {
        atomicInteger.getAndIncrement();
    }

    private LongAdder longAdder = new LongAdder();

    public void clickByLongAdder() {
        longAdder.increment();
    }

    private LongAccumulator longAccumulator = new LongAccumulator(Long::sum, 0);

    public void clickByLongAccumulator() {
        longAccumulator.accumulate(1);
    }

    public int getNumber() {
        return number;
    }

    public int getAtomicInteger() {
        return atomicInteger.get();
    }

    public long getLongAdder() {
        return longAdder.sum();
    }

    public long getLongAccumulator() {
        return longAccumulator.get();
    }
}
